package com.zareal.ymcc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.zareal.ymcc.StrUtils;
import com.zareal.ymcc.VerifyCodeUtils;
import com.zareal.ymcc.constans.CommonConstants;
import com.zareal.ymcc.domain.BlackList;
import com.zareal.ymcc.domain.MessageSms;
import com.zareal.ymcc.dto.RedisRegisterDto;
import com.zareal.ymcc.dto.SmsDto;
import com.zareal.ymcc.enums.GlobalErrorCode;
import com.zareal.ymcc.properties.SmsRegisterProperties;
import com.zareal.ymcc.service.IBlackListService;
import com.zareal.ymcc.service.IverifyCodeService;
import com.zareal.ymcc.util.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IverifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SmsRegisterProperties smsRegisterProperties;

    @Autowired
    private IBlackListService blackListService;


    @Override
    public String getImgCode(String key) {
        // 生成随机的数
        String code = StrUtils.getComplexRandomString(1);

        // 设置概数字存在的时间
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        // 使用工具编码编码成base64
        String base64Str = VerifyCodeUtils.verifyCode(110, 40, code);
        return base64Str;
    }


    // 获取短信验证码
    @Override
    public void getSmsMessage(SmsDto dto) {
        String phone = dto.getMobile();
        String code = dto.getImageCode();
        String password = dto.getPassword();
        String imageCodeKey = dto.getImageCodeKey();

        // 1.判断传过来的参数是否为空
//        if (dto.getMobile() == null) {
//            throw new GlobalCustomException(GlobalErrorCode.PARAM_IS_NULL_ERROR);
//        }
        // 判断手机号为空
        AssertUtil.isPhone(phone,GlobalErrorCode.PHONE_IS_NULL_ERROR);

        // 检验黑名单 查询对象
//        BlackList oneBlack = selectByPhone(phone);
        String blackKey  = String.format(CommonConstants.Register_BLACK_PREFIX,phone);
        Object o = redisTemplate.opsForValue().get(blackKey);
        AssertUtil.isNull(o,GlobalErrorCode.BLACK_PHONE);
        // todo
//        if (dto.getImageCode() == null) {
//            throw new GlobalCustomException(GlobalErrorCode.PHONE_IS_NULL_ERROR);
//        }
        // 判断验证码是否为空
        AssertUtil.isNotNull(code,GlobalErrorCode.IMAGECODE_IS_NULL);
//        if (dto.getPassword() == null) {
//            throw new GlobalCustomException(GlobalErrorCode.PHONE_IS_NULL_ERROR);
//        }
        // 断言密码是否为空
        AssertUtil.isNotNull(password,GlobalErrorCode.PASSWORD_IS_NULL);
        // 2.判断redis的验证码是否过期
        String imageCode = redisTemplate.opsForValue().get(imageCodeKey).toString();
        Date newTime = new Date();
//        if (imageCode == null) {
//            throw new GlobalCustomException(GlobalErrorCode.IMAGECODE_IS_NULL);
//        }
        // 判断redis里面验证码是否为过期或者不存在
        AssertUtil.isNotNull(imageCode,GlobalErrorCode.IMAGECODE_IS_NULL);
        // 2.1不为空继续判断传过来的两个验证码是否正确
//        if (!imageCode.toString().equalsIgnoreCase(dto.getImageCode())) {
//            throw new GlobalCustomException(GlobalErrorCode.IMAGECODE_IS_ERROR);
//        }
        AssertUtil.isEqualsIgnoreCase(imageCode,code,GlobalErrorCode.IMAGECODE_IS_ERROR);
        // 3.判断手机号是否注册过
        // 4.判断手机号验证码
        // 4.1获取redis中的手机验证码，判断是否需要生成手机验证码
        String key = String.format(CommonConstants.Register_PHONE_PREFIX, phone);
        Object phoneCode = redisTemplate.opsForValue().get(key);
        if (phoneCode != null) {
            // 判断验证码时间是否过了一分钟
            RedisRegisterDto registerDto = (RedisRegisterDto)phoneCode;


//            if (){
//                throw new GlobalCustomException(GlobalErrorCode.IMAGECODE_IS_ERROR);
//            }
            AssertUtil.isFalse((newTime.getTime() - registerDto.getTime()) < smsRegisterProperties.getInterval(),GlobalErrorCode.PHONECODETIME_TOO_SHORT);
            // 超过一分钟重新生成之前的验证码
            phoneCode = registerDto.getCode();

        } else {// 为空创建新的code
            phoneCode = StrUtils.getRandomString(smsRegisterProperties.getCodelength());

        }
        RedisRegisterDto redisRegisterDto = new RedisRegisterDto(phoneCode.toString(),newTime.getTime());
        redisTemplate.opsForValue().set(key, redisRegisterDto,
                smsRegisterProperties.getTimeout(), TimeUnit.MINUTES);
        String content = String.format(smsRegisterProperties.getSmsmessage(), phoneCode);
        senMessage(newTime, content);

    }
    // 获取黑名单
    private BlackList selectByPhone(String phone) {
        Wrapper<BlackList> wrapper = new EntityWrapper<>();
        wrapper.eq("phone",phone);
        BlackList blackList = blackListService.selectOne(wrapper);
        return blackList;
    }

    private void senMessage(Date newTime, String content) {
        // 发送短信
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(smsRegisterProperties.getSmstitle());
        messageSms.setContent(content);
        messageSms.setSendTime(newTime);
        // 从请求头中获取ip
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getRemoteUser();
        messageSms.setIp(ip);
        log.info(content);
    }

}
